﻿/*
 * protocol.hpp
 *
 *  Created on: 2017年2月7日
 *      Author: work
 */

#ifndef _DM_PROTOCOL_PROTOCOL_HPP_
#define _DM_PROTOCOL_PROTOCOL_HPP_

#include <dm/export.hpp>

#ifndef DM_API_PROTOCOL
#define DM_API_PROTOCOL DM_API_IMPORT
#endif

#include <dm/protocol/protocolbase.hpp>
#include <dm/msg/types.hpp>
#include <dm/os/ascom/timer.hpp>
#include <ctime>

namespace dm{
namespace protocol{

/**
 * 规约类
 * 引入任务处理模型
 */
class DM_API_PROTOCOL CProtocol:public CProtocolBase{
public:
	/**
	 * 任务状态
	 */
	enum ETaskState{
		None,   //!< None 	无
		Settled,//!< Settled 任务标志设置
		Started,//!< Started 任务已经启动
		Success,//!< Success 任务执行成功
		Fail,   //!< Fail		任务执行失败
		Permit, //!< Permit  任务不允许
		Timeout //!< Timeout	任务超时
	};

	/*
	 * 消息对象索引
	 */
	typedef dm::msg::index_t index_t;

	typedef dm::msg::SCallInfo::group_t 		group_t;		//!< 召唤组类型
	typedef dm::msg::ERemoteControl     	rmtctl_t;	    //!< 远控类型
	typedef dm::msg::SParaData						para_t;		//!< 参数类型
	typedef dm::msg::ESyncDataType			sync_t;		//!< 同步类型

	typedef dm::CRunTimeStamp::sec_t sec_t;		//!< 时间秒类型

	CProtocol();
	virtual ~CProtocol();

	virtual EAction timedRefresh( const ts_t& ts,const rts_t& rts );

	virtual void reset( const ts_t& ts,const rts_t& rts );

	inline const ETaskState& getTaskCall()const{
		return m_taskCall;
	}

	inline const ETaskState& getTaskSyncClock()const{
		return m_taskClock;
	}

	inline const ETaskState& getTaskRemoteCtl()const{
		return m_taskRmtCtl;
	}

	inline const ETaskState& getTaskParameters()const{
		return m_taskParas;
	}

	inline const ETaskState& getTaskSync()const{
		return m_taskSync;
	}

	inline const ETaskState& getTaskReset()const{
		return m_taskReset;
	}

	/**
	 * 获取召唤组信息
	 * @return
	 */
	inline const group_t& getCallGroup()const{
		return m_callGroup;
	}

	inline const rmtctl_t& getRemoteControl()const{
		return m_rmtctl;
	}

	inline const index_t& getRemoteControlAddress()const{
		return m_rmtctlIndex;
	}

	inline const bool& isParaSet()const{
		return m_paraSet;
	}

	inline const para_t& getParameters()const{
		return m_paraData;
	}

	inline const sync_t& getSyncType()const{
		return m_syncType;
	}

	// timeout <0 永不超时
	inline void setTimeout_call( const sec_t& timeout=-1 ){
		m_timeout_call = timeout;
	}

	inline const sec_t& getTimeout_call()const{
		return m_timeout_call;
	}

	inline void setTimeout_clock( const sec_t& timeout=-1 ){
		m_timeout_clock = timeout;
	}

	inline const sec_t& getTimeout_clock()const{
		return m_timeout_clock;
	}

	inline void setTimeout_rmtctl( const sec_t& timeout=-1 ){
		m_timeout_rmtclt = timeout;
	}

	inline const sec_t& getTimeout_rmtctl()const{
		return m_timeout_rmtclt;
	}

	inline void setTimeout_paras( const sec_t& timeout=-1 ){
		m_timeout_paras = timeout;
	}

	inline const sec_t& getTimeout_paras()const{
		return m_timeout_paras;
	}

	inline void setTimeout_sync( const sec_t& timeout=-1 ){
		m_timeout_sync = timeout;
	}

	inline const sec_t& getTimeout_sync()const{
		return m_timeout_sync;
	}

	inline void setTimeout_reset( const sec_t& timeout=-1 ){
		m_timeout_reset = timeout;
	}

	inline const sec_t& getTimeout_reset()const{
		return m_timeout_reset;
	}

	virtual bool setTask_call( const ts_t& ts,const rts_t& rts,const group_t& group=0,const sec_t& timeout=0 );
	virtual bool setTask_syncClock( const ts_t& ts,const rts_t& rts,const sec_t& timeout = 0 );
	virtual bool setTask_remoteControl( const ts_t& ts,const rts_t& rts,const rmtctl_t& rc,const index_t& addr,const sec_t& timeout=0 );
	virtual bool setTask_parasSetUint8( const ts_t& ts,const rts_t& rts,const index_t& addr,const index_t& size,const dm::uint8* data,const sec_t& timeout=0 );
	virtual bool setTask_parasSetInt8( const ts_t& ts,const rts_t& rts,const index_t& addr,const index_t& size,const dm::int8* data,const sec_t& timeout=0 );
	virtual bool setTask_parasSetUint16( const ts_t& ts,const rts_t& rts,const index_t& addr,const index_t& size,const dm::uint16* data,const sec_t& timeout=0 );
	virtual bool setTask_parasSetInt16( const ts_t& ts,const rts_t& rts,const index_t& addr,const index_t& size,const dm::int16* data,const sec_t& timeout=0 );
	virtual bool setTask_parasSetUint32( const ts_t& ts,const rts_t& rts,const index_t& addr,const index_t& size,const dm::uint32* data,const sec_t& timeout=0 );
	virtual bool setTask_parasSetInt32( const ts_t& ts,const rts_t& rts,const index_t& addr,const index_t& size,const dm::int32* data,const sec_t& timeout=0 );
	virtual bool setTask_parasSetUint64( const ts_t& ts,const rts_t& rts,const index_t& addr,const index_t& size,const dm::uint64* data,const sec_t& timeout=0 );
	virtual bool setTask_parasSetInt64( const ts_t& ts,const rts_t& rts,const index_t& addr,const index_t& size,const dm::int64* data,const sec_t& timeout=0 );
	virtual bool setTask_parasSetFloat32( const ts_t& ts,const rts_t& rts,const index_t& addr,const index_t& size,const dm::float32* data,const sec_t& timeout=0 );
	virtual bool setTask_parasSetFloat64( const ts_t& ts,const rts_t& rts,const index_t& addr,const index_t& size,const dm::float64* data,const sec_t& timeout=0 );
	virtual bool setTask_parasGet( const ts_t& ts,const rts_t& rts,const index_t& addr,const index_t& size,const sec_t& timeout=0 );
	virtual bool setTask_syncData( const ts_t& ts,const rts_t& rts,const sync_t& type,const sec_t& timeout=0 );
	virtual bool setTask_reset( const ts_t& ts,const rts_t& rts,const sec_t& timeout=0 );

	inline bool setTask_call( const ts_t& ts,const rts_t& rts,const dm::msg::SCallInfo& info,const sec_t& timeout=0 ){
		return setTask_call(ts,rts,info.group,timeout);
	}

	inline bool setTask_remoteControl( const ts_t& ts,const rts_t& rts,const dm::msg::SRemoteCtlInfo& info,const sec_t& timeout=0 ){
		return setTask_remoteControl(ts,rts,info.remoteCtl,info.index,timeout);
	}

	inline bool setTask_parasSet( const ts_t& ts,const rts_t& rts,const dm::msg::SParaData& info,const sec_t& timeout=0 ){
		switch( info.type ){
		case dm::msg::SParaData::DtUint8:
			return setTask_parasSetUint8( ts,rts,info.index,info.num,info.as_uint8(),timeout);
		case dm::msg::SParaData::DtInt8:
			return setTask_parasSetInt8( ts,rts,info.index,info.num,info.as_int8(),timeout);
		case dm::msg::SParaData::DtUint16:
			return setTask_parasSetUint16( ts,rts,info.index,info.num,info.as_uint16(),timeout);
		case dm::msg::SParaData::DtInt16:
			return setTask_parasSetInt16( ts,rts,info.index,info.num,info.as_int16(),timeout);
		case dm::msg::SParaData::DtUint32:
			return setTask_parasSetUint32( ts,rts,info.index,info.num,info.as_uint32(),timeout );
		case dm::msg::SParaData::DtInt32:
			return setTask_parasSetInt32( ts,rts,info.index,info.num,info.as_int32(),timeout);
		case dm::msg::SParaData::DtUint64:
			return setTask_parasSetUint64( ts,rts,info.index,info.num,info.as_uint64(),timeout);
		case dm::msg::SParaData::DtInt64:
			return setTask_parasSetInt64( ts,rts,info.index,info.num,info.as_int64(),timeout);
		case dm::msg::SParaData::DtFloat32:
			return setTask_parasSetFloat32( ts,rts,info.index,info.num,info.as_float32(),timeout);
		case dm::msg::SParaData::DtFloat64:
			return setTask_parasSetFloat64( ts,rts,info.index,info.num,info.as_float64(),timeout);
		default:
			return false;
		}
	}

	inline bool setTask_parasGet( const ts_t& ts,const rts_t& rts,const dm::msg::SParaInfo& info,const sec_t& timeout=0 ){
		return setTask_parasGet( ts,rts,info.index,info.num,timeout);
	}

	inline bool setTask_syncData( const ts_t& ts,const rts_t& rts,const dm::msg::SSyncInfo& info,const sec_t& timeout=0 ){
		return setTask_syncData( ts,rts,info.type,timeout);
	}

	virtual bool endTask_call( const ts_t& ts,const rts_t& rts,const ETaskState& result );
	virtual bool endTask_syncClock( const ts_t& ts,const rts_t& rts,const ETaskState& result );
	virtual bool endTask_remoteControl( const ts_t& ts,const rts_t& rts,const ETaskState& result );
	virtual bool endTask_paraSet( const ts_t& ts,const rts_t& rts,const ETaskState& result );
	virtual bool endTask_paraGetUint8( const ts_t& ts,const rts_t& rts,const ETaskState& result,const index_t& size=0,const dm::uint8* data=0 );
	virtual bool endTask_paraGetInt8( const ts_t& ts,const rts_t& rts,const ETaskState& result,const index_t& size=0,const dm::int8* data=0 );
	virtual bool endTask_paraGetUint16( const ts_t& ts,const rts_t& rts,const ETaskState& result,const index_t& size=0,const dm::uint16* data=0 );
	virtual bool endTask_paraGetInt16( const ts_t& ts,const rts_t& rts,const ETaskState& result,const index_t& size=0,const dm::int16* data=0 );
	virtual bool endTask_paraGetUint32( const ts_t& ts,const rts_t& rts,const ETaskState& result,const index_t& size=0,const dm::uint32* data=0 );
	virtual bool endTask_paraGetInt32( const ts_t& ts,const rts_t& rts,const ETaskState& result,const index_t& size=0,const dm::int32* data=0 );
	virtual bool endTask_paraGetUint64( const ts_t& ts,const rts_t& rts,const ETaskState& result,const index_t& size=0,const dm::uint64* data=0 );
	virtual bool endTask_paraGetInt64( const ts_t& ts,const rts_t& rts,const ETaskState& result,const index_t& size=0,const dm::int64* data=0 );
	virtual bool endTask_paraGetFloat32( const ts_t& ts,const rts_t& rts,const ETaskState& result,const index_t& size=0,const dm::float32* data=0 );
	virtual bool endTask_paraGetFloat64( const ts_t& ts,const rts_t& rts,const ETaskState& result,const index_t& size=0,const dm::float64* data=0 );
	virtual bool endTask_syncData( const ts_t& ts,const rts_t& rts,const ETaskState& result );
	virtual bool endTask_reset( const ts_t& ts,const rts_t& rts,const ETaskState& result );

	inline bool endTask_paraGet( const ts_t& ts,const rts_t& rts,const ETaskState& result,const dm::msg::SParaData& pd ){
		switch( pd.type ){
		case dm::msg::SParaData::DtUint8:
			return endTask_paraGetUint8( ts,rts,result,pd.num,pd.as_uint8());
		case dm::msg::SParaData::DtInt8:
			return endTask_paraGetInt8( ts,rts,result,pd.num,pd.as_int8());
		case dm::msg::SParaData::DtUint16:
			return endTask_paraGetUint16( ts,rts,result,pd.num,pd.as_uint16());
		case dm::msg::SParaData::DtInt16:
			return endTask_paraGetInt16( ts,rts,result,pd.num,pd.as_int16());
		case dm::msg::SParaData::DtUint32:
			return endTask_paraGetUint32( ts,rts,result,pd.num,pd.as_uint32());
		case dm::msg::SParaData::DtInt32:
			return endTask_paraGetInt32( ts,rts,result,pd.num,pd.as_int32());
		case dm::msg::SParaData::DtUint64:
			return endTask_paraGetUint64( ts,rts,result,pd.num,pd.as_uint64());
		case dm::msg::SParaData::DtInt64:
			return endTask_paraGetInt64( ts,rts,result,pd.num,pd.as_int64());
		case dm::msg::SParaData::DtFloat32:
			return endTask_paraGetFloat32( ts,rts,result,pd.num,pd.as_float32());
		case dm::msg::SParaData::DtFloat64:
			return endTask_paraGetFloat64( ts,rts,result,pd.num,pd.as_float64());
		default:
			return false;
		}
	}

protected:
	virtual EAction refresh_msg( const ts_t& ts,const rts_t& rts );

	virtual EAction refresh_call( const ts_t& ts,const rts_t& rts );
	virtual EAction refresh_syncClock( const ts_t& ts,const rts_t& rts );
	virtual EAction refresh_remoteCtl( const ts_t& ts,const rts_t& rts );
	virtual EAction refresh_paras( const ts_t& ts,const rts_t& rts );
	virtual EAction refresh_syncData( const ts_t& ts,const rts_t& rts );
	virtual EAction refresh_reset( const ts_t& ts,const rts_t& rts );

	virtual void checkNewTask( const ts_t& ts,const rts_t& rts );

	/**
	 * 空闲任务
	 * 一般执行链路测试，或者自动触发任务.由最终实现的子类来实现。
	 * @param txFrame
	 * @return
	 */
	virtual EAction task_none( const ts_t& ts,const rts_t& rts );

	/**
	 * 任务启动
	 * @param txFrame
	 * @return
	 */
	virtual EAction taskStart_call( const ts_t& ts,const rts_t& rts );
	virtual EAction taskStart_syncClock( const ts_t& ts,const rts_t& rts );
	virtual EAction taskStart_remoteControl( const ts_t& ts,const rts_t& rts );
	virtual EAction taskStart_parameters( const ts_t& ts,const rts_t& rts );
	virtual EAction taskStart_syncData( const ts_t& ts,const rts_t& rts );
	virtual EAction taskStart_reset( const ts_t& ts,const rts_t& rts );

	/**
	 * 任务执行
	 * @param txFrame
	 * @return
	 */
	virtual EAction taskDo_call( const ts_t& ts,const rts_t& rts );
	virtual EAction taskDo_syncClock( const ts_t& ts,const rts_t& rts );
	virtual EAction taskDo_remoteControl( const ts_t& ts,const rts_t& rts );
	virtual EAction taskDo_parameters( const ts_t& ts,const rts_t& rts );
	virtual EAction taskDo_syncData( const ts_t& ts,const rts_t& rts );
	virtual EAction taskDo_reset( const ts_t& ts,const rts_t& rts );

	/**
	 * 任务结束
	 * @param txFrame
	 * @return
	 */
	virtual EAction taskEnd_call( const ts_t& ts,const rts_t& rts );
	virtual EAction taskEnd_syncClock( const ts_t& ts,const rts_t& rts );
	virtual EAction taskEnd_remoteControl( const ts_t& ts,const rts_t& rts );
	virtual EAction taskEnd_parameters( const ts_t& ts,const rts_t& rts );
	virtual EAction taskEnd_syncData( const ts_t& ts,const rts_t& rts );
	virtual EAction taskEnd_reset( const ts_t& ts,const rts_t& rts );

private:
	inline bool isEndState( const ETaskState& state )const{
		return state==Success || state==Fail || state==Permit || state==Timeout;
	}

protected:
	ETaskState m_taskCall;		// 召唤任务状态
	ETaskState m_taskClock;		// 时钟同步任务状态
	ETaskState m_taskRmtCtl;	// 远控任务状态
	ETaskState m_taskParas;		// 参数任务状态
	ETaskState m_taskSync;		// 同步任务状态
	ETaskState m_taskReset;		// 复位任务状态

	group_t m_callGroup;			// 召唤组参数： 一般 0：总召，其他组号

	rmtctl_t m_rmtctl;			// 任务标志：远动
	index_t m_rmtctlIndex;		// 远动地址：这个地址代表了系统内的远动地址索引

	bool m_paraSet;				// 参数任务是否是设置
	para_t m_paraData;			// 参数任务数据

	sync_t m_syncType;	  // 同步任务类型

	rts_t m_tsCall;	    // 召唤任务起始时刻
	rts_t m_tsClock;	// 对时任务起始时刻
	rts_t m_tsRmtCtl;	// 远控任务起始时刻
	rts_t m_tsParas;	// 参数任务起始时刻
	rts_t m_tsSync;	    // 同步任务起始时刻
	rts_t m_tsReset;	// 复位任务起始时刻

	sec_t m_timeout_call;	// 总召超时
	sec_t m_timeout_clock;	// 时钟同步超时
	sec_t m_timeout_rmtclt;	// 远控超时
	sec_t m_timeout_paras;	// 参数超时
	sec_t m_timeout_sync;	// 同步超时
	sec_t m_timeout_reset;	// 复位超时

	bool m_ackCall;		// 召唤任务需要应答
	bool m_ackClock;  	// 时钟同步任务需要应答
	bool m_ackRmtCtl;	// 远控任务需要应答
	bool m_ackParas;	// 参数命令需要应答
	bool m_ackSync;		// 同步命令需要应答
	bool m_ackReset;	// 复位命令需要应答
};

}
}



#endif /* INCLUDE_DM_PROTOCOL_PROTOCOL_HPP_ */
